﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;

namespace Might.Infrastructure.DOM {

    /// <summary>
    /// Special version of Observable Collection, wrapper for our IDomNodes.
    /// </summary>
    public interface IDomNodeCollection : IList<IDomNode>, INotifyCollectionChanged {
    
        string GroupName { get; }
        IDomNode Owner { get; }
        
    }

    /// <summary>
    /// Currently the only implmentation of IDomNodeCollection
    /// </summary>
    public class DomNodeCollection : IDomNodeCollection {

        /// <summary>
        /// 
        /// </summary>
        private readonly ObservableCollection<IDomNode> collection = new ObservableCollection<IDomNode>();

        /// <summary>
        /// 
        /// </summary>
        private string groupName;
        private IDomNode owner;

        public event NotifyCollectionChangedEventHandler CollectionChanged;

        public DomNodeCollection( string groupName , IDomNode owner ) {
            this.groupName = groupName;
            this.owner = owner;
            collection.CollectionChanged += collection_CollectionChanged;
        }

        #region IList<IDomNode> Members

        public int IndexOf(IDomNode item) {
            return collection.IndexOf(item);
        }

        public void Insert(int index, IDomNode item) {
            if (checkAddedItemType(item)) {
                collection.Insert(index, item);
            } else {
                throw new ArgumentException("This item can not be added to this DomNodeCollection");
            }
        }

        public void RemoveAt(int index) {
            collection.RemoveAt(index);
        }

        public IDomNode this[int index] {
            get { return collection[index]; }
            set {
                if (checkAddedItemType(value)) {
                    collection[index] = value;
                } else {
                    throw new ArgumentException("This item can not be added to this DomNodeCollection");
                }
            }
        }

        #endregion

        #region ICollection<IDomNode> Members

        public void Add(IDomNode item) {
            if (checkAddedItemType(item)) {
                collection.Add(item);
            } else {
                throw new ArgumentException("This item can not be added to this DomNodeCollection");
            }
        }

        public void Clear() {
            collection.Clear();
        }

        public bool Contains(IDomNode item) {
            return collection.Contains(item);
        }

        public void CopyTo(IDomNode[] array, int arrayIndex) {
            collection.CopyTo(array, arrayIndex);
        }

        public int Count {
            get { return collection.Count; }
        }

        public bool IsReadOnly {
            get { return false; }
        }

        public bool Remove(IDomNode item) {
            return collection.Remove(item);
        }

        #endregion

        #region IEnumerable<IDomNode> Members

        public IEnumerator<IDomNode> GetEnumerator() {
            return collection.GetEnumerator();
        }

        #endregion

        #region IEnumerable Members

        IEnumerator IEnumerable.GetEnumerator() {
            return collection.GetEnumerator();
        }

        #endregion

        #region IDomNodeCollection Members

        public string GroupName {
            get { return groupName; }
        }

        public IDomNode Owner {
            get { return owner;  }
        }

        #endregion

        protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e) {
            if (CollectionChanged != null) {
                CollectionChanged(this, e);
            }
        }

        private void collection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) {
            OnCollectionChanged(e);
        }

        private bool checkAddedItemType(IDomNode newItem) {
            //TODO check type according the groupName of this DomNodeCollection !!!
            return true;
        }

    }
}
